#ifndef __ITERATOR_H__
#define __ITERATOR_H__
#include <iostream>
#include <cstdio>
#include <cstring>


template<class T>
class Iterator{
public:
    virtual ~Iterator(){};
    virtual void next() = 0;
    virtual bool hasNext() = 0;
    virtual void first() = 0;
    virtual T& currentItem()=0;
};


template<class T>
class MyContainer{
public:
    virtual ~MyContainer(){}
    virtual Iterator<T>* CreateIterator() = 0;
    virtual int getSize() = 0;
    virtual T& getItem(int index) = 0;
    virtual void push_back(T&) = 0;
    virtual void push_back(T&&) = 0;
};

template<class T>
class MyVectorIter : public Iterator<T>{
public:
    MyVectorIter(MyContainer<T>* c):m_vec(c),current(0){}
    ~MyVectorIter(){}
    virtual void next(){
        current++;
    }
    virtual void first(){
        current=0;
    }
    virtual bool hasNext(){
        if(current < m_vec->getSize() - 1)
            return true;
        return false;
    }
    virtual T& currentItem(){
        return m_vec->getItem(current);
    }

private:
    MyContainer<T>* m_vec;
    int current;

};

template<class T>
class MyVector : public MyContainer<T>{
public:
    MyVector(int size):m_size(size),m_cur(0){
        m_arr = new T[size];
    }
    ~MyVector(){}
    virtual Iterator<T>* CreateIterator(){
        return new MyVectorIter<T>(this);
    }

    virtual T& getItem(int index){
        return m_arr[index];
    }
    virtual void push_back(T& value){
        if(m_cur < m_size)
        {
            m_arr[m_cur++] = value;
        }
        else{
            T* temp = m_arr;
            m_arr = new T[2*m_size];
            memcpy((char*)m_arr,(char*)temp,sizeof(T)*m_cur);
            delete[] temp;
            m_size=2*m_size;
            m_arr[m_cur++] = value;
        }
    }
    virtual void push_back(T&& value){
        if(m_cur < m_size)
        {
            m_arr[m_cur++] = value;
        }
        else{
            T* temp = m_arr;
            m_arr = new T[2*m_size];
            memcpy((char*)m_arr,(char*)temp,sizeof(T)*m_cur);
            delete[] temp;
            m_size=2*m_size;
            m_arr[m_cur++] = value;
        }
    }
    virtual int getSize(){
        return m_cur+1;
    }
private:
    int m_size;
    int m_cur;
    T* m_arr;

};
#endif